package com.tebiecloud.yunst.server.controller.feign;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.tebiecloud.common.model.ResultBody;
import com.tebiecloud.common.utils.DateUtils;
import com.tebiecloud.common.utils.ResultBodyUtils;
import com.tebiecloud.common.utils.StringUtils;
import com.tebiecloud.yunst.client.constants.ResultEnum;
import com.tebiecloud.yunst.client.model.entity.YunAgentCollect;
import com.tebiecloud.yunst.client.model.entity.YunStUser;
import com.tebiecloud.yunst.client.model.entity.YunWithdrawApply;
import com.tebiecloud.yunst.client.model.vo.PayInfoVO;
import com.tebiecloud.yunst.client.service.IYunStPaymentServiceClient;
import com.tebiecloud.yunst.server.service.YunAgentCollectService;
import com.tebiecloud.yunst.server.service.YunStUserService;
import com.tebiecloud.yunst.server.service.YunWithdrawApplyService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/feign/payment")
public class PaymentController implements IYunStPaymentServiceClient {

    @Autowired
    private YunAgentCollectService yunAgentCollectService;

    @Autowired
    private YunWithdrawApplyService yunWithdrawApplyService;

    @Autowired
    private YunStUserService yunStUserService;

    @PostMapping("consumeApply")
    @Override
    public ResultBody<PayInfoVO> consumeApply(
            @RequestParam(value = "userId") Long userId,
            @RequestParam(value = "orderId") Long orderId,
            @RequestParam(value = "amount") Integer amount,
            @RequestParam(value = "payMethodStr",defaultValue = "WECHAT_PUBLIC",required = false) String payMethodStr,
            @RequestParam(value = "openId") String openId,
            @RequestParam(value = "expiredTime") int expiredTime) {
        PayInfoVO payInfoVO = new PayInfoVO();
        //校验金额是否为0
        if(amount<=0){
            //返回金额不能小于0
            return ResultBodyUtils.build(ResultEnum.YUN_AGENT_COLLECT_AMOUNT.getCode(),ResultEnum.YUN_AGENT_COLLECT_AMOUNT.getMessage());
        }
        //查询有无这个用户
        QueryWrapper<YunStUser> yunStUserQueryWrapper = new QueryWrapper<>();
        yunStUserQueryWrapper.eq("user_id",userId);
        YunStUser yunStUser = yunStUserService.getOne(yunStUserQueryWrapper);
        if(yunStUser==null){
            //创建新用户
            Map<String,Object> map = yunStUserService.createOrUpdate(userId,"weChatPublic",openId);
            if(map.get("status").equals("error")){
                return ResultBodyUtils.build(ResultEnum.YUN_ST_USER_CREATE_ERROR.getCode(),map.get("message").toString());
            }else{
                yunStUser = (YunStUser) map.get("yunStUser");
            }
        }else{
            //没有绑定用户标识
            if(StringUtils.isEmpty(yunStUser.getAcct())){
               Map<String,String> map = yunStUserService.applyBindAcct(yunStUser.getBizUserId(),"weChatPublic",openId);
               if(map.get("status").equals("error")){
                   return ResultBodyUtils.build(ResultEnum.YUN_ST_USER_CREATE_ERROR.getCode(),map.get("message").toString());
               }
            }
        }
        //查询有无这个订单的支付信息
        QueryWrapper<YunAgentCollect> yunAgentCollectQueryWrapper = new QueryWrapper<>();
        yunAgentCollectQueryWrapper.eq("order_id",orderId);
        yunAgentCollectQueryWrapper.eq("pay_status",0);
        YunAgentCollect yunAgentCollect = yunAgentCollectService.getOne(yunAgentCollectQueryWrapper);
        if(yunAgentCollect != null && yunAgentCollect.getAmount().equals(amount)){//有则返回预支付信息
            payInfoVO.setAppId(yunAgentCollect.getAppId());
            payInfoVO.setNonceStr(yunAgentCollect.getNonceStr());
            payInfoVO.setPackageStr(yunAgentCollect.getPackageStr());
            payInfoVO.setPaySign(yunAgentCollect.getPaySign());
            payInfoVO.setPrepayid(yunAgentCollect.getPrepayId());
            payInfoVO.setSignType(yunAgentCollect.getSignType());
            payInfoVO.setTimeStamp(yunAgentCollect.getTimeStamp());
            payInfoVO.setCt(yunAgentCollect.getCt());
        }else{//没有则调用第三方消费接口创建支付信息
            //先更新上一条数据为过期
            UpdateWrapper<YunAgentCollect> yunAgentCollectUpdateWrapper = new UpdateWrapper<>();
            yunAgentCollectUpdateWrapper.eq("order_id",orderId);
            YunAgentCollect updateYunAgent = new YunAgentCollect();
            updateYunAgent.setPayStatus(2);
            yunAgentCollectService.update(updateYunAgent,yunAgentCollectUpdateWrapper);
            String bizUserId = "#yunBizUserId_B2C#";//收款方为商户
            HashMap<String, String> resultMap = yunAgentCollectService.consumeApply(yunStUser.getBizUserId(),bizUserId,orderId,userId,amount,payMethodStr,openId,expiredTime);
            if(StringUtils.isNotEmpty(resultMap.get("status")) && resultMap.get("status").equals("error")){
                return ResultBodyUtils.build(Integer.valueOf(resultMap.get("code")),resultMap.get("message"));
            }else{
                payInfoVO.setAppId(resultMap.get("appId"));
                payInfoVO.setPrepayid(resultMap.get("prepayid"));
                payInfoVO.setNonceStr(resultMap.get("nonceStr"));
                payInfoVO.setPackageStr(resultMap.get("packageStr"));
                payInfoVO.setTimeStamp(resultMap.get("timeStamp"));
                payInfoVO.setSignType(resultMap.get("signType"));
                payInfoVO.setPaySign(resultMap.get("paySign"));
                payInfoVO.setCt(new Date());
            }
        }
        return ResultBodyUtils.ok(payInfoVO);
    }

    /**
     * 获取支付信息
     * @param orderId
     * @return
     */
    @PostMapping("paymentInfo")
    @Override
    public ResultBody<PayInfoVO> paymentInfo(@RequestParam(value = "orderId") Long orderId) {
        QueryWrapper<YunAgentCollect> yunAgentCollectQueryWrapper = new QueryWrapper<YunAgentCollect>();
        yunAgentCollectQueryWrapper.eq("order_id",orderId);
        yunAgentCollectQueryWrapper.notIn("pay_status",2);
        yunAgentCollectQueryWrapper.orderByDesc("ct");
        List<YunAgentCollect> yunAgentCollectList =  yunAgentCollectService.list(yunAgentCollectQueryWrapper);
        PayInfoVO payInfoVO = new PayInfoVO();
        if(yunAgentCollectList.size()>0){
            payInfoVO.setPrepayid(yunAgentCollectList.get(0).getPrepayId());
            payInfoVO.setTimeStamp(yunAgentCollectList.get(0).getTimeStamp());
            payInfoVO.setSignType(yunAgentCollectList.get(0).getSignType());
            payInfoVO.setPaySign(yunAgentCollectList.get(0).getPaySign());
            payInfoVO.setPackageStr(yunAgentCollectList.get(0).getPackageStr());
            payInfoVO.setNonceStr(yunAgentCollectList.get(0).getNonceStr());
            payInfoVO.setAppId(yunAgentCollectList.get(0).getAppId());
            payInfoVO.setCt(yunAgentCollectList.get(0).getCt());
        }else{
            return ResultBodyUtils.build(ResultEnum.YUN_PAYINFO_NOT_FOUND.getCode(),ResultEnum.YUN_PAYINFO_NOT_FOUND.getMessage());
        }
        return ResultBodyUtils.ok(payInfoVO);
    }

    @PostMapping("agentCollect")
    public ResultBody agentCollect(
            @RequestParam(value = "payerId") String payerId,
            @RequestParam(value = "bizUserId") String bizUserId,
            @RequestParam(value = "orderNo") Long orderNo,
            @RequestParam(value = "amount") Integer amount,
            @RequestParam(value = "payMethodStr") String payMethodStr,
            @RequestParam(value = "wxOpenId") String wxOpenId){
        //校验金额大于0
        if(amount<=0){
            return ResultBodyUtils.build(ResultEnum.YUN_AGENT_COLLECT_AMOUNT.getCode(),ResultEnum.YUN_AGENT_COLLECT_AMOUNT.getMessage());
        }
        //校验账号
        YunStUser payerUser = getEntityByBizUserId(payerId);
        if(payerUser==null){
            return ResultBodyUtils.build(ResultEnum.YUN_ST_USER_NOT_FIND.getCode(),ResultEnum.YUN_ST_USER_NOT_FIND.getMessage());
        }
        if(StringUtils.isEmpty(payerUser.getAcct())){
            return ResultBodyUtils.build(ResultEnum.YUN_ST_AGENT_ACCT.getCode(),ResultEnum.YUN_ST_AGENT_ACCT.getMessage());
        }
        YunStUser recieverUser = getEntityByBizUserId(bizUserId);
        if(recieverUser==null){
            return ResultBodyUtils.build(ResultEnum.YUN_ST_USER_NOT_FIND.getCode(),ResultEnum.YUN_ST_USER_NOT_FIND.getMessage());
        }
        HashMap<String, String> resultMap = yunAgentCollectService.agentCollect(payerId,bizUserId,orderNo,amount,payMethodStr,wxOpenId);
        if(resultMap.get("status").equals("error")){
           return ResultBodyUtils.build(Integer.valueOf(resultMap.get("code")),resultMap.get("message"));
        }
        return ResultBodyUtils.ok(resultMap);
    }

    /**
     * 支付回调
     * @param rps
     */
    @RequestMapping("payCallBack")
    @Override
    public ResultBody<YunAgentCollect> payCallBack(@RequestParam(value = "rps") String rps) {
        JSONObject requset = JSON.parseObject(rps);
        JSONObject returnValue = requset.getJSONObject("returnValue");
        String status =  requset.getString("status");
        String bizOrderNo = returnValue.getString("bizOrderNo");
        int result = yunAgentCollectService.payCallBack(bizOrderNo,status);
        if(result==0){
            return ResultBodyUtils.failed();
        }
        QueryWrapper<YunAgentCollect> yunUniteControllerQueryWrapper = new QueryWrapper<>();
        yunUniteControllerQueryWrapper.eq("biz_order_no",bizOrderNo);
        YunAgentCollect yunAgentCollect = yunAgentCollectService.getOne(yunUniteControllerQueryWrapper);
        return ResultBodyUtils.ok(yunAgentCollect);
    }

    /**
     * 私用查询用户是否存在
     * @param bizUserId
     * @return
     */
    private YunStUser getEntityByBizUserId(String bizUserId){
        QueryWrapper<YunStUser> queryWrapper = new QueryWrapper<YunStUser>();
        queryWrapper.eq("biz_user_id",bizUserId);
        return yunStUserService.getOne(queryWrapper);
    }

    @RequestMapping("updateYunAgentCollect")
    @Override
    public ResultBody updateYunAgentCollect(@RequestParam(value = "orderId") long orderId,
                                            @RequestParam(value = "payStatus") int payStatus) {
        QueryWrapper<YunAgentCollect> yunAgentCollectQueryWrapper = new QueryWrapper<>();
        yunAgentCollectQueryWrapper.eq("order_id",orderId);
        yunAgentCollectQueryWrapper.eq("pay_status",0);
        YunAgentCollect yunAgentCollect = yunAgentCollectService.getOne(yunAgentCollectQueryWrapper);
        if(yunAgentCollect!=null && yunAgentCollect.getPayStatus().equals(0)){
            UpdateWrapper<YunAgentCollect> yunAgentCollectUpdateWrapper = new UpdateWrapper<>();
            yunAgentCollectUpdateWrapper.eq("agent_collect_id",yunAgentCollect.getAgentCollectId());
            YunAgentCollect yunAgentCollect1 = new YunAgentCollect();
            yunAgentCollect1.setPayStatus(payStatus);
            yunAgentCollectService.update(yunAgentCollect1,yunAgentCollectUpdateWrapper);
        }
        return ResultBodyUtils.ok();
    }

    @RequestMapping("withdrawCallBack")
    @Override
    public ResultBody<YunWithdrawApply> withdrawCallBack(@RequestParam(value = "rps") String rps) {
        JSONObject requset = JSON.parseObject(rps);
        JSONObject returnValue = requset.getJSONObject("returnValue");
        String status =  requset.getString("status");
        String bizOrderNo = returnValue.getString("bizOrderNo");
        QueryWrapper<YunWithdrawApply> yunWithdrawApplyQueryWrapper = new QueryWrapper<>();
        yunWithdrawApplyQueryWrapper.eq("biz_order_no",bizOrderNo);
        YunWithdrawApply yunWithdrawApply = new YunWithdrawApply();
        yunWithdrawApply.setStatus(1);
        yunWithdrawApply.setArrivedTime(new Date());
        yunWithdrawApplyService.update(yunWithdrawApply,yunWithdrawApplyQueryWrapper);
        return ResultBodyUtils.ok(yunWithdrawApply);
    }
}
